package com.recharge.utils;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * HttpClient的封装类
 */
public class HttpClientUtils {

    private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);

    private static PoolingHttpClientConnectionManager cm;

    private static final int CONNECTION_TIMEOUT = 2000;


    static {
        //多连接的线程安全的管理器
        cm = new PoolingHttpClientConnectionManager();
        cm.setDefaultMaxPerRoute(30); //每个主机的最大并行链接数
        cm.setMaxTotal(200);          //客户端总并行链接最大数
    }

    /**
     * 默认的系统超时时间
     */
    public final static int DEFAULT_TIMEOUT = 15000;

    /**
     * HttpClient直接连接接口，直接返回数据
     *
     * @param url        接口URL
     * @param requestMap NameValuePair参数
     * @param encoding   编码
     * @param timeout    超时时间
     * @return 结果报文
     * @throws Exception
     */
    public static String invokePostHttp(String url, Map<String, String> requestMap, String encoding, int timeout) throws Exception{
        logger.debug("send http post start. Uri:{}, Entity:{}", url, requestMap);
        HttpPost httpMethod = new HttpPost(url);
        String returnMsg = null;
        //设置post方法体
        setPostEntity(requestMap, encoding, httpMethod);

        //执行发送
        returnMsg = doSend(encoding, timeout, httpMethod);
        return returnMsg;
    }

    /**
     * HttpClient直接连接接口，直接返回数据
     *
     * @param url        接口URL
     * @param requestMap NameValuePair参数
     * @param encoding   编码
     * @return 结果报文
     * @throws Exception
     */
    public static String invokePostHttp(String url, Map<String, String> requestMap, String encoding) throws Exception {
        return invokePostHttp(url, requestMap, encoding, DEFAULT_TIMEOUT);
    }

    public static String invokeGetHttp(String url, String encoding, int timeout) throws Exception {
        logger.debug("send http get start. Uri:{}, Entity:{}", url);
        HttpGet httpMethod = new HttpGet(url);

        //执行发送
        String returnMsg = doSend(encoding, timeout, httpMethod);
        return returnMsg;
    }

    /**
     * HttpClient直接连接接口，直接返回数据
     *
     * @param url          接口URL
     * @param stringEntity post请求的字符串参数
     * @param encoding     编码
     * @param timeout      超时时间
     * @return 结果报文
     * @throws Exception
     */
    public static String invokePostString(String url, StringEntity stringEntity,
                                   String encoding, int timeout) throws Exception {
        logger.debug("send http post start. Uri:{}, Entity:{}", url, EntityUtils.toString(stringEntity));
        HttpPost httpPost = new HttpPost(url);
        String returnMsg = "";
        try {
            CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();

            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(timeout)
                    .setConnectTimeout(CONNECTION_TIMEOUT)
                    .build();
            httpPost.setConfig(requestConfig);
            httpPost.setEntity(stringEntity);
            httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=" + encoding);
            httpPost.addHeader("Connection", "close");
            httpPost.addHeader("Accept-Language", "zh-cn");
            long startTime = System.currentTimeMillis();
            HttpResponse httpResponse = httpClient.execute(httpPost);
            long sendTime = System.currentTimeMillis() - startTime;
            HttpEntity httpEntity = httpResponse.getEntity();
            if (httpEntity != null) {
                returnMsg = EntityUtils.toString(httpEntity,encoding);
                returnMsg = returnMsg.replaceAll("script", "").replaceAll("html", "");
                EntityUtils.consume(httpEntity);
            }
            logger.debug("send http post request end. response:{}. cost time :{}", returnMsg, sendTime);
        }finally {
            if (httpPost != null) {
                httpPost.releaseConnection();
            }
        }
        return returnMsg;
    }


    private static String doSend(String encoding, int timeout, HttpRequestBase httpRequest) throws Exception {
        String returnMsg = "";
        try {

            CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();

            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(timeout)
                    .setConnectTimeout(CONNECTION_TIMEOUT)
                    .build();
            httpRequest.setConfig(requestConfig);
            httpRequest.addHeader("Connection", "close");
            httpRequest.addHeader("Accept-Language", "zh-cn");
            long startTime = System.currentTimeMillis();
            CloseableHttpResponse httpResponse = httpClient.execute(httpRequest);
            long sendTime = System.currentTimeMillis() - startTime;
            HttpEntity httpEntity = httpResponse.getEntity();
            if (httpEntity != null) {
                returnMsg = EntityUtils.toString(httpEntity,encoding);
                EntityUtils.consume(httpEntity);
            }
            logger.debug("send http request end. response:{},cost time :{}", returnMsg , sendTime);
        }finally {
            if (httpRequest != null) {
                httpRequest.releaseConnection();
            }
        }
        return returnMsg;
    }


    private static void setPostEntity(Map<String, String> requestMap, String encoding, HttpPost httpMethod) throws UnsupportedEncodingException {
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        // 先迭代HashMap
        Iterator<Entry<String, String>> it = requestMap.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, String> entry = it.next();
            String key = entry.getKey();
            nvps.add(new BasicNameValuePair(key, entry.getValue()));
        }
        httpMethod.setEntity(new UrlEncodedFormEntity(nvps, encoding));
    }


    public static void main(String[] args) throws Exception {
        System.out.println(HttpClientUtils.invokeGetHttp("http://www.baidu.com","gbk",3000));
    }

}